//libmychat
package main

import "C"

import (
	"fmt"
	"math/rand"
	"strings"
	"sync"
	"time"
)

type ChanMsg struct {
	From, Msg string
}

var (
	buf     string
	bot     Bot
	step    int
	verbose bool
	chan1   chan ChanMsg
	lock    sync.RWMutex
)

//export IrcGetMsg
func IrcGetMsg(from, msg **C.char) int {
	m, ok := <-chan1
	var ret int
	if ok {
		*from = C.CString(m.From)
		*msg = C.CString(m.Msg)
		ret = 1
	} else {
		*from = nil
		*msg = nil
		ret = 0
	}
	return ret
}

//export IrcInit
func IrcInit(verb C.int) {
	rand.Seed(time.Now().UnixNano())
	step = 1
	chan1 = make(chan ChanMsg, 1)
	if verb == 1 {
		verbose = true
	} else {
		verbose = false
	}
}

//export IrcSetServer
func IrcSetServer(s *C.char) int {
	var ss = C.GoString(s)
	if ss == "" {
		bot.server = "chat.freenode.net:6667"
	} else {
		bot.server = ss
	}
	//returnMsg("sys", bot.server)
	step++
	return step //2
}

//export IrcSetNick
func IrcSetNick(s *C.char) int {
	var ss = C.GoString(s)
	if ss == "" {
		bot.User = fmt.Sprintf("talker%d", rand.Uint32())
	} else {
		bot.User = ss
	}
	bot.Nick = bot.User
	//returnMsg("sys", bot.Nick)
	step++
	return step //3
}

//export IrcSetRoom
func IrcSetRoom(s *C.char, channel **C.char) int {
	var ss = C.GoString(s)
	if ss == "" {
		bot.Channel = fmt.Sprintf("#xtalk%d", rand.Uint32())
	} else {
		bot.Channel = fmt.Sprintf("#xtalk%s", ss)
	}
	*channel = C.CString(bot.Channel)
	//returnMsg("sys", bot.Channel)
	step++
	return step //4
}

//export IrcSetKey
func IrcSetKey(k *C.char) int {
	var ss = C.GoString(k)
	if len(ss) > 3 {
		bot.Crypto.SetKey(ss)
		step++
		go loopRecv()
	}
	return step //5
}

//export IrcGetHead
func IrcGetHead(connected C.int) *C.char {
	var stat string
	if connected == 1 {
		stat = "connected"
	} else {
		stat = "connecting"
	}
	res := fmt.Sprintf("%s / %s / %s    %s", bot.server,
		strings.TrimPrefix(bot.Channel, "#xtalk"), bot.Nick, stat)
	return C.CString(res)
}

//export IrcQuit
func IrcQuit() {
	bot.Close()
	step = 1
}

//export IrcSay
func IrcSay(target, str *C.char) {
	if step > 5 {
		bot.PrivMsgTo(C.GoString(target), C.GoString(str))
	}
}

//export IrcGetStep
func IrcGetStep() int {
	lock.RLock()
	ret := step
	lock.RUnlock()
	return ret
}

func returnMsg(from, msg string) {
	var m = ChanMsg{From: from, Msg: msg}
	chan1 <- m
}

func loopRecv() {
	bot.Connect()
	bot.Command("MODE", bot.Channel, "+s")
	for {
		message, err := bot.Recv()
		if err != nil {
			//log.Println(err)
			//log.Println("Exit Now!")
			returnMsg("sys", "Exit Now!")
			close(chan1)
			break
		}

		if message.Command == "JOIN" {
			//connected
			//log.Printf("%v %v\n", message.Prefix.Name, message.Command)
			returnMsg("/join", message.Prefix.Name)
			lock.Lock()
			if step < 6 && message.Prefix.Name == bot.Nick {
				step = 6 //6
				returnMsg("sys", "you join")
			}
			lock.Unlock()
		} else if message.Command == "QUIT" {
			returnMsg("/quit", message.Prefix.Name)
		} else if message.Command == "PING" {
			bot.Send(fmt.Sprintf("PONG %d", time.Now().UnixNano()))
			//log.Println("SEND: PONG")
		} else if message.Command == "PRIVMSG" {
			// Do Something with this msg
			rmsg := message.Params[1]
			dmsg := bot.Crypto.Decode(rmsg)
			var msg string
			if dmsg == nil {
				msg = fmt.Sprintf("%s %s", "[Not Secret]", rmsg)
			} else {
				msg = string(dmsg)
			}
			//var name1, err = hex.DecodeString(strings.TrimPrefix(message.Prefix.Name, "user"))
			name1 := message.Prefix.Name
			if err == nil {
				//log.Printf("%v:%v\n", string(name1), msg)
				returnMsg(string(name1), msg)
			}
		} else if message.Command == "353" {
			//353: /names list
			returnMsg("/names", message.Params[3])
		} else if message.Command == "PART" {
			//PART: leave
			returnMsg("/part", message.Prefix.Name)
		} else if verbose {
			//log.Printf("%v\n", message)
			msg := fmt.Sprintf("%s:%s", message.Command, strings.Join(message.Params, ","))
			returnMsg(message.Prefix.Name, msg)
		}
	}
}

func main() {}
